home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
IRIX Installation Tools & Overlays 2001 November
/
SGI IRIX Installation Tools & Overlays 2001 November - Disc 1.iso
/
dist
/
roboinst.idb
/
usr
/
etc
/
roboinst_start.z
/
roboinst_start
Wrap
Text File
|
2001-10-10
|
41KB
|
1,553 lines
#! /bin/sh
#Tag 0x00000f00
#ident "$Revision $"
# Copyright 1997-2000, Silicon Graphics, Inc.
# All Rights Reserved.
#
# This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
# the contents of this file may not be disclosed to third parties, copied or
# duplicated in any form, in whole or in part, without the prior written
# permission of Silicon Graphics, Inc.
#
# RESTRICTED RIGHTS LEGEND:
# Use, duplication or disclosure by the Government is subject to restrictions
# as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
# and Computer Software clause at DFARS 252.227-7013, and/or in similar or
# successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
# rights reserved under the Copyright Laws of the United States.
# roboinst_start
#
# Do not run this script directly. See roboinst(1M) for details.
#
# This script verifies that roboinst configuration information is
# available, then restarts the system in roboinst mode or runs live.
#
# In miniroot mode (standard) it checks to see if the sa bootfile in
# the specified bootdir can be read, then attempts to download the
# custom configuration information. The mrconfig file is parsed for
# loghost, and the roboinst checkpoint file is written in /var/inst.
# The volume header is then poked, and the machine is rebooted, with
# nvram mrmode set to either custom or customdebug.
#
# In live mode it attempts to download the custom configuration
# information and starts a live roboinst session.
usage="error: please use roboinst(1M)"
PATH=/sbin:/usr/bin:/usr/bsd:/usr/sbin:/etc:/usr/etc:
umask 022
test "$TMPDIR" = "" && {
TMPDIR=/tmp
export TMPDIR
}
INSTRBASE=
CHECKPOINT=/var/inst/.roboinst_status
BPCLT=/usr/etc/bootpc
GETHOSTBYNAME=/usr/etc/gethostbyname
SYSLOGCONF=/etc/syslog.conf
CUSTOM=$TMPDIR/d.roboinst.$$
MRCONF=mrconfig
MRCONFIG=$CUSTOM/$MRCONF
MREXPORTS=$CUSTOM/$MRCONF.exports
INDEXFILE=.index
LOGOK="nologmsg ok"
ERROR="nologmsg error"
WARNING="nologmsg warning"
INFO="nologmsg info"
DEBUG=":"
ROBOINSTLOG=/var/inst/.roboinstlog
DBGFD=-
LOGGER="logger -t roboinst"
TMPFILE=$TMPDIR/roboinst.$$
TMPROOT=$TMPDIR/roboroot.$$
ECHO=echo
# The highest version of mrconfig we understand.
# DEFVERS is assumed if mrconfig contains no "version" keyword.
MAXVERS=1
DEFVERS=1
# The RoboInst version number, to manage updates:
VERSION="1.1"
msgfile=uxsgicore
# Check the user id.
if [ -x /usr/bin/id ]; then
eval `/usr/bin/id | sed 's/[^a-z0-9=].*//'`
if [ "${uid:=0}" -ne 0 ]; then
printf "`gettxt ${msgfile}:710 '%s: Only root can run /etc/shutdown.'`\n" $0
exit 2
fi
fi
#
# Process options and arguments
#
confirmation=""
timestr=""
bootdir=""
configdir=""
debugmode=""
disksetup=""
syspart=""
grace="60"
livemode=""
reportaddr=""
netmode=""
versiononly=""
emailaddr=""
while getopts b:c:dg:Lm:nN:pP:st:V:yqz OPT; do
case $OPT in
b) bootdir="$OPTARG";;
c) configdir="$OPTARG";;
d) DEBUG=echo; DBGFD=1; debugmode=debug;;
g) grace="$OPTARG";;
L) livemode=yes;;
m) emailaddr="$OPTARG";;
n) confirmation=no;;
N) netmode="$OPTARG";;
p) syspart=yes;;
P) syspart="$OPTARG";;
s) disksetup=disksetup;;
t) timestr="$OPTARG";;
V) versiononly="$OPTARG";;
y) confirmation=yes;;
z) reportaddr=yes;;
q) ECHO=:;;
*) echo $usage; exit 2
esac
done
if [ "$versiononly" = "0" ] ; then
echo $VERSION
exit 0
elif [ "$versiononly" != "" ] ; then
expr "$versiononly" ">=" "$VERSION" >/dev/null
exit $?
fi
if [ "$configdir" = "" ]; then
echo $usage
exit 2
fi
if [ "$bootdir" = "" -a "$livemode" = "" ]; then
echo $usage
exit 2
fi
# configdhcp contains the possible dhcp mode: [%!+]
case $netmode in
local|LOCAL|none|NONE) configdhcp='!' ;;
bootp*|BOOTP*|*1533) configdhcp='%' ;;
dhcp|DHCP) configdhcp='+' ;;
*) configdhcp="" ;;
esac
#
# ---- define some functions ----
#
# I18N
# ----------------------------------------------------------------------------
ask() {
#! ask msg default
#! default should be 0 for "no", "yes" otherwise
#! returns 0 for "no", otherwise "yes"
yesstr=`gettxt ${msgfile}:171 "yes"`
nostr=`gettxt ${msgfile}:172 "no"`
choicefmt=`gettxt ${msgfile}:169 "(%s/%s)"`
defaultfmt=`gettxt ${msgfile}:170 "[%s]"`
shortyes=`echo $yesstr | cut -c1`
shortno=`echo $nostr | cut -c1`
fmt=${choicefmt}${defaultfmt}
if [ $2 -eq 0 ]; then
str=`printf "${choicefmt}${defaultfmt} : " "$yesstr" "$nostr" "$nostr"`
else
str=`printf "${choicefmt}${defaultfmt} : " "$yesstr" "$nostr" "$yesstr"`
fi
printf "%s%s" "$1" "$str"
read ans
# convert answer to lowercase
ans=`echo $ans | tr '[A-Z]' '[a-z]'`
case "$ans" in
${yesstr}*) ret=1
;;
${nostr}*) ret=0
;;
${shortyes}*) ret=1
;;
${shortno}*) ret=0
;;
*) ret=$2
;;
esac
return ${ret}
} # End of ask
msgfile=uxsgicore
# ----------------------------------------------------------------------------
#
# the following functions are copied wholesale from
# eoe/cmd/initpkg/mrcustomrc.sh so that changes should be mirrored
# in both places
#
#------- functions copied from eoe/cmd/initpkg/mrcustomrc.sh --------
# Send a log message to various places
logmsg()
{
if [ "$1" = "ok" ]; then
shift 2>/dev/null ; mstate="$1" ; shift 2>/dev/null
msg="state=$mstate status=0 $*"
elif [ "$1" = "error" ]; then
shift 2>/dev/null ; mstate="$1" ;
shift 2>/dev/null ; mstatus="$1" ; shift 2>/dev/null
msg="state=$mstate status=$mstatus error: $*"
elif [ "$1" = "warning" ]; then
shift 2>/dev/null
msg="warning: $*"
elif [ "$1" = "info" ]; then
shift 2>/dev/null
msg="$*"
else
msg="$*"
fi
$LOGGER "$msg"
echo "roboinst: $msg"
if [ -f $ROBOINSTLOG ]; then
# queue remote msgs until loghost is known
echo "$msg" >> $ROBOINSTLOG
fi
}
# Generate statements of the form: "A=val ; export A ; B=val ; export B ; "
# to represent SGI_CAPACITY and SGI_CAP_<device>
disk_capacity()
{
# Set SGI_CAP_<device>
(cd /dev/scsi && ls -1|grep '^sc'|xargs -n10 scsicontrol -c \
| sed -n 's/^sc\([0-9]*\)d\([0-9]*\)l\([0-9]*\):.*capacity=\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*/SGI_CAP_dks\1d\2vol=\4 ; export SGI_CAP_dks\1d\2vol ; /p')
# Set SGI_CAPACITY for root device
( cd /dev/rdsk && \
rootdev=`stat -rq root` && \
test "$rootdev" && \
for f in dks* ; do
test "$f" && \
test "`stat -rq $f`" = "$rootdev" && {
ff=`echo $f|sed -n 's/^dks\([0-9]*\)d\([0-9]*\)s\([0-9]*\)/dks\1d\2/p'`
echo "SGI_CAPACITY=\$SGI_CAP_${ff}vol ; export SGI_CAPACITY ; "
break;
}
done )
}
# Build the export file $MREXPORTS. This holds environment
# variables that will be exported over the course of the miniroot
# session. We only construct the file once, then . it in later
# invocations of mrcustomrc.
build_exports()
{
inst -H > $TMPFILE 2>&-
SGI_CPUBOARD=`sed -n 's/^CPUBOARD=//p' $TMPFILE`
SGI_CPUARCH=`sed -n 's/^CPUARCH=//p' $TMPFILE|grep -iv MIPS`
SGI_VIDEO=`sed -n 's/^VIDEO=//p' $TMPFILE`
SGI_ABI=`sed -n 's/^CPUARCH=//p' $TMPFILE|grep -i MIPS`
SGI_GFXBOARD=`sed -n 's/^GFXBOARD=//p' $TMPFILE`
SGI_SUBGR=`sed -n 's/^SUBGR=//p' $TMPFILE`
SGI_MODE=`sed -n 's/^MODE=//p' $TMPFILE`
SGI_MACHINE=`sed -n 's/^MACHINE=//p' $TMPFILE`
rm -f $TMPFILE 2>&-
SGI_ROOT=$INSTRBASE
SGI_CUSTOM=$CUSTOM
SGI_SYSID="$chaddr"
SGI_IPADDR="$netaddr"
SGI_HOSTNAME=`sed -n p /etc/sys_id 2>&-`
SGI_MEMSIZE=`hinv | sed -n 's/.*Main memory size: \([0-9]*\) Mbytes.*/\1/p'`
bootfile="$bootdir"
SGI_BOOTSERVER=`echo "$bootfile" | sed -n 's;:.*;;p'`
SGI_BOOTDIR=`echo "$bootfile" | sed -e 's;.*:;;' -e 's;^/sa$;/;' -e 's;/sa;;' -e 's;^sa$;.;'`
# default is to use DHCP, so that empty $configdir does the right thing
# NOTE: this check is in multiple locations!
# see also mrcustomrc in the miniroot
case "$configdhcp" in
!*)
# don't do any DHCP stuff
SGI_NETINQUIRY="NONE"
;;
+*)
# DHCP assignes IP address if it is available
SGI_NETINQUIRY="DHCP"
;;
%*|*)
# use extended BOOTP protocol
# (use IP address from nvram, but ask for network parameters)
SGI_NETINQUIRY="BOOTP1533"
;;
esac
SGI_CONFIGSERVER=`echo "$configdir" | sed -n 's;:.*;;p'`
SGI_CONFIGDIR=`echo "$configdir" | sed -e 's;.*:;;'`
SGI_SYSTEMPART=`devnm / | sed 's/. .*/0/'`
SGI_SYSTEMDISK=`echo "$SGI_SYSTEMPART" | sed 's/s[0-9]*$//'`
rm -f $MREXPORTS 2>&-
( for var in SGI_CPUBOARD SGI_GFXBOARD SGI_SUBGR SGI_VIDEO \
SGI_CPUARCH SGI_ABI SGI_MODE SGI_MACHINE \
SGI_ROOT SGI_CUSTOM \
SGI_SYSID SGI_IPADDR SGI_HOSTNAME \
SGI_BOOTSERVER SGI_BOOTDIR SGI_CONFIGSERVER SGI_CONFIGDIR \
SGI_SYSTEMPART SGI_SYSTEMDISK \
SGI_MEMSIZE SGI_NETINQUIRY ; do
eval "echo \"\$$var\"" | \
sed -e 's/"/\\"/g' \
-e 's/\(.*\)/'$var'="\1"; export '$var'/'
done
disk_capacity 2>&-
) > $MREXPORTS
}
# tftp remote file ($1) to local file ($2) using
# mode ($3). Suppress msg if quiet is 1 ($4).
dotftp()
{
tstat=0
if [ "$3" != "" ]; then
MODE=$3
else
MODE=binary
fi
test "$4" != 1 && $DEBUG tftp $1 $2
tftp <<- EOF >$TMPFILE 2>&1
mode $MODE
get $1 $2
quit
EOF
test "$?" != 0 -o ! -f "$2" && {
cat $TMPFILE
tstat=1
}
rm -f $TMPFILE >/dev/null 2>&1
return $tstat
}
# test whether a file ($1) has the expected size ($2)
chksize()
{
test "$2" = "" && return 0
s=`/sbin/stat -qs $1`
test "$s" != "$2" && \
{ $ERROR init 1 "Size mismatch for $1 $s (expected $2)";
$ERROR init 1 "Try re-running roboinst_config on the configuration directory";
return 1; }
return 0
}
# test whether a file ($1) has the expected checksum ($2)
chksum()
{
test "$2" = "" && return 0
s=`sum -r $1 | nawk '{print $1}'`
test "$s" != "$2" && \
{ $ERROR init 1 "Checksum mismatch for $1 $s (expected $2)";
$ERROR init 1 "Try re-running roboinst_config on the configuration directory";
return 1; }
return 0
}
# $1 = remote pathname, $2 = local pathname, $3 = tftp(0)/rcp(1), $4= attrs
filecopy()
{
type=""
size=""
sum=""
mode=""
# parse valid attrs into local vars
eval ` echo "$4" | \
nawk \
' { for (i=1; i <= NF; ++i)
if (match($i,"^size=")) {
s=substr($i,RSTART+RLENGTH,length($i)-RLENGTH);
if (match(s,"^[0-9][0-9]*$"))
printf("size=%s;",s);
} else if (match($i,"^sum=")) {
s=substr($i,RSTART+RLENGTH,length($i)-RLENGTH);
if (match(s,"^[0-9][0-9]*$"))
printf("sum=%s;",s);
} else if (match($i,"^type=")) {
s=substr($i,RSTART+RLENGTH,length($i)-RLENGTH);
if (match(s,"^[fd]*$"))
printf("type=%s;",s);
} else if (match($i,"^mode=")) {
s=substr($i,RSTART+RLENGTH,length($i)-RLENGTH);
if (match(s,"^[0-7][0-7]*$"))
printf("mode=%s;",substr(s,length(s)-3,3));
}
} ' `
if [ "$type" = "" -o "$type" = "f" ]; then
if [ $3 -eq 0 ]; then
dotftp $1 $2
else
rcp -v $1 $2 >&$DBGFD 2>&$DBGFD
fi
( test $? -eq 0 &&
chksize $2 $size &&
chksum $2 $sum &&
chmod $mode $2 ) || return 1
elif [ "$type" = "d" ]; then
$DEBUG mkdir $2
( mkdir -p $2 &&
chmod $mode $2 ) || return 1
else
$ERROR init 1 "Unknown filetype $type"
return 1
fi
return 0
}
# $1 = remote dir (from), $2 = local dir (to), $3 = tftp(0) or rcp(1)
dircopy()
{
mkdir -p $2 || return 1
rm -f $2/$INDEXFILE >/dev/null 2>&1
if [ $3 -eq 0 ]; then
dotftp $1/$INDEXFILE $2/$INDEXFILE ascii 1
else
rcp -v $1/$INDEXFILE $2/$INDEXFILE >&$DBGFD 2>&$DBGFD
fi
( test $? -eq 0 && test -s $2/$INDEXFILE) || {
$DEBUG "dircopy: no index file $1/$INDEXFILE"
rm -f $2/$INDEXFILE >/dev/null 2>&1 # in case it was empty
if [ $3 -eq 0 ]; then
dotftp $1/$MRCONF $2/$MRCONF ascii 1
else
rcp -v $1/$MRCONF $2/$MRCONF >&$DBGFD 2>&$DBGFD
fi
( test $? -eq 0 && test -s $2/$MRCONF) || {
$DEBUG "dircopy: no configuration file $1/$MRCONF"
rm -f $2/$MRCONF >/dev/null 2>&1 # in case it was empty
return 1
}
return 0
}
( ret=0;
while read pathname attrs ; do
echo "$pathname" | grep '^#' >/dev/null || \
filecopy $1/$pathname $2/$pathname $3 "$attrs" || ret=1
done;
return $ret ) < $2/$INDEXFILE || return 1
return 0
}
# Copy the remote scripts ($1) to a local dir ($2),
# $3 is the hardware address, and $4 is the IP address
# ($3 and $4 and not currently used.)
getcustom()
{
remote="$1"
local="$2"
$DEBUG "getcustom $1 $2 $3 $4"
for src in $remote
do
rm -fr $local >/dev/null 2>&1
dircopy $src $local 0 && {
$LOGOK custom "using configuration $src"
return 0
}
done
echo "$remote" | grep "^.*@.*:" > /dev/null || \
remote="guest@$remote"
for src in $remote
do
rm -fr $local >/dev/null 2>&1
dircopy $src $local 1 && {
$LOGOK custom "using configuration $src"
return 0
}
done
rm -fr $local >/dev/null 2>&1
return 1
}
# Preprocess the setenv and if/then/else conditionals
# in the mrconfig file, and generate separate files such
# as /custom/mrconfig.preinst for each phase.
preprocess()
{
test -f $MRCONFIG && \
nawk -v p=1 -v top=-1 -v cfg=$MRCONFIG \
'function unexpected(kwd,line)
{ printf "ERROR: unexpected \"%s\" keyword at line %d\n", kwd, line; }
BEGIN { # the files for these phases are written
# raw, without the #!/bin/sh heading and
# opening environment section.
special["partition"] = 1;
special["onerror"] = 1;
special["loghost"] = 1;
special["version"] = 1;
special["nokernel"] = 1;
special["inst"] = 1;
# for these phases, write a separate side-file
# that contains the environment.
sepenv["inst"] = 1;
# slines[scount] is an array containing all
# the setenv commands we have seen thus far.
scount =0;
# name of temp file for variable expansions
srand;
envfile = "/tmp/roboenv" rand;
}
{ if (match($1, "^#")) {
next;
} else if ($1 == "if") {
sub($1,"",$0);
if ($NF == "then")
sub("then[ \t]*$","",$0);
t = p ? system(envargs " " $0) : 0;
pstack[++top] = p;
ifstack[top] = "if";
tstack[top] = t;
p = p && (t == 0);
next;
} else if ($1 == "elsif" || $1 == "elif") {
if (ifstack[top] != "if" && ifstack[top] != "elsif")
{ unexpected($1, FNR); next; }
sub($1,"",$0);
if ($NF == "then")
sub("then[ \t]*$","",$0);
ifstack[top] = "elsif";
if ((top < 0 || pstack[top]) && tstack[top] != 0)
t = system(envargs " " $0);
else
t = 1;
if (tstack[top] == 0)
t = 1;
else
tstack[top] = t;
p = (top < 0 || pstack[top]) && (t == 0);
next;
} else if ($1 == "else") {
if (ifstack[top] != "if" && ifstack[top] != "elsif")
{ unexpected($1, FNR); next; }
ifstack[top] = "else";
p = (top < 0 || pstack[top]) && (tstack[top] != 0);
next;
} else if ($1 == "endif" || $1 == "fi") {
if (ifstack[top] != "if" && ifstack[top] != "elsif" && ifstack[top] != "else")
{ unexpected($1, FNR); next; }
p = pstack[top--];
next;
}
if (!p) next;
if (match($1, "setenv>?") && length($2) > 0) {
# expand the envargs string for later use in
# this nawk script (when we run condition
# subprocesses above), and also save the environment
# setting in the file mrconfig.setenv.
var = $2;
val = $0;
sub("^[ \t]*setenv>?[ \t]+" var "[ \t]*", "", val);
if (!match(val, "^[A-Za-z0-9_\.\-]*$")) {
# do shell expansion
syscmd=sprintf(envargs " echo %s > %s", val, envfile);
system(syscmd);
getline val < envfile;
close(envfile);
}
ENVIRON[var] = val;
gsub("\"", "\\\"", val);
envargs = envargs var "=\"" val "\" ; export " var " ; ";
outfile = cfg ".setenv";
setcmd = sprintf ("%s=\"%s\"; export %s", var, val, var);
printf "%s\n", setcmd > outfile;
slines[scount++] = setcmd;
} else if (NF > 0) {
# save this line in corresponding output file
line = $0;
phase = $1;
sub(">$","",phase);
outfile = cfg "." phase;
if (!seenfile[phase]) {
seenfile[phase] = 1;
if (!special[phase]) {
# unless this phase is 'special', write the
# interpreter line, and any lines from the
# mrconfig.setenv file we have accumulated thus far.
printf "#!/bin/sh\n" > outfile
for (s=0; s<scount; ++s)
printf "%s\n", slines[s] > outfile;
system("chmod 755 " outfile);
}
if (sepenv[phase]) {
# some phases needed a separate environment file
# so remember the current contents of mrconfig.setenv
# as mrconfig.setenv.inst, for example.
system("cp " cfg ".setenv " cfg ".setenv." phase " 2>&-");
}
}
sub("^[ \t]*" phase ">?($|[ \t])", "", line);
if (special[phase]) {
# do envvar substitution for phases that
# are not interpreted by /bin/sh
while (1) {
if (match(line, "^\\$[A-Za-z_]+"))
;
else if (match(line, "[^\\\\]\\$[A-Za-z_]+"))
{ RSTART += 1; RLENGTH -=1 }
else
break;
line = substr(line,1,RSTART-1) \
ENVIRON[substr(line, RSTART+1, RLENGTH-1)] \
substr(line,RSTART+RLENGTH,length(line));
}
}
if (phase == "partition") {
# substitute systemdisk keywords in partition statements
w="";
if (match(line, "^[ \t]*")) w=substr(line, RSTART, RLENGTH);
if (sub("^[ \t]*systemdisk", "", line)) {
# if partition was omitted assume 0
if (match(line, "^[0-9]|^vh|^vol"))
line = w ENVIRON["SGI_SYSTEMDISK"] "s" line; # dks0d1 + s + line
else
line = w ENVIRON["SGI_SYSTEMPART"] line; # dks0d1s0
}
}
printf "%s\n", line > outfile;
}
}
END { system(sprintf("rm %s 2>&-", envfile)) }' $MRCONFIG
}
# Derive the fstab from the partition statements in the mrconfig
# file, and print results on stdout
buildfstab()
{
nawk ' { if ($3 != "swap" && $4 != "nomount") {
dev = match($1,"^/") ? $1 : "/dev/dsk/" $1;
type = $3;
dir = $4;
sub("/.*","",type);
if (type == "option" || type == "root")
type = "xfs";
if (type != "xfs" && type != "nfs" && type != "efs")
next;
opt = ""
# optional mount options are terminated
# by optional semicolon.
for (i=5; i <= NF && $i != ";"; ++i)
if (opt == "")
opt = $i;
else
opt = opt " " $i;
if (opt == "") {
if (type == "nfs") {
opt="ro,soft,bg"
} else {
rdev=dev;
sub("^/dev/dsk", "/dev/rdsk", rdev);
opt = "rw,raw=" rdev;
}
}
if (dir != "")
printf "%s %s %s %s 0 0\n", dev, dir, type, opt;
}
} ' $MRCONFIG.partition 2>&-
}
# Run user sh commands in the mrconfig file labeled with
# pattern ($1). Additional args ($2, $3, ...) are passed
# as positional parameters.
runuser()
{
phase=$1
runfile=$MRCONFIG.$phase
shift
if [ -x $runfile ]; then
$runfile $*
istat=$?
if [ $istat = 0 ]; then
$LOGOK $phase ok
else
$ERROR $phase "$istat" "failed"
fi
fi
}
#------- end of functions from mrcustomrc.sh --------
#------- begin other functions --------
# get the IP address for a given host ($1)
# returns the IP address in IPADDR global variable
# returns 1 if got a name
getipaddr()
{
hostname="$1"
if [ ! -x $GETHOSTBYNAME ]; then
$ERROR init 1 "$GETHOSTBYNAME not installed, unable to lookup $hostname"
exit 1
fi
IPADDR=`$GETHOSTBYNAME $hostname | \
nawk -v a=0 '/^'$hostname' / { a=$3; exit }
END { print a }'`
test "$IPADDR" != "0" && return 0
return 1
}
#------- begin functions for live roboinst -------
# add a host or hosts to the syslog
syslog_addhost()
{
tmp1=$SYSLOGCONF.1.$$
tmp2=$SYSLOGCONF.2.$$
getipaddr `hostname`
thisip=$IPADDR
cp $SYSLOGCONF $tmp1
for host in $* ; do
( if [ "$host" = "localhost" ]; then
IPADDR=$thisip
else
getipaddr $host
fi
grep -v '@'$IPADDR'[^-a-zA-Z0-9_.]?' $tmp1
if [ "$thisip" != "$IPADDR" ]; then
echo '## remote loghost @'$IPADDR' ##'
echo 'kern.debug\t|/usr/sbin/klogpp\t@'$IPADDR
echo '*.debug;kern.none\t@'$IPADDR
echo '## done loghost @'$IPADDR' ##'
fi ) >$tmp2 2>/dev/null
mv $tmp2 $tmp1
done
if [ -s $tmp1 ]; then
# save original for syslog_restore()
mv $SYSLOGCONF $SYSLOGCONF.$$
# move new file into place
mv $tmp1 $SYSLOGCONF
killall -HUP syslogd
fi
rm -f $tmp1 $tmp2 2>/dev/null
}
# restore original syslog configuration
syslog_restore()
{
if [ -s $SYSLOGCONF.$$ ]; then
rm -f $SYSLOGCONF 2>/dev/null
mv $SYSLOGCONF.$$ $SYSLOGCONF
killall -HUP syslogd
fi
}
# returns the name of the builtin ethernet interface, the one that the PROM
# and miniroot will use (first).
# (mostly copied from mrnetrc, which is derived from init.d/network)
defaultinterface()
{
hinv -c network | sed -ne 's/^Integr.* \([a-z][a-z]*0\),.*$/\1/p'
}
get_config()
{
# get net address and netmask of PROM boot interface
promif=`defaultinterface`
ifstr=`ifconfig $promif`
ifup=`echo $ifstr | grep UP`
if [ -z "$ifup" -a "$livemode" != "yes" ] ; then
$ERROR init 1 "Miniroot boot interface $promif is not active, aborting"
exit 1
fi
netaddr=`echo $ifstr | nawk '{
for(i=1; i<NF; ++i) {
if ($i ~ /inet/){print $(i+1);}
}}'`
netmask=`echo $ifstr | nawk '{
for(i=1; i<NF; ++i) {
if ($i ~ /netmask/){print $(i+1);}
}}'`
$DEBUG "Assuming current IP address $netaddr, netmask $netmask"
chaddr=`/usr/etc/netstat -ian -I $promif | nawk '/:/ {print $1}'`
# copy the client configuration directory, check attributes
getcustom "$configdir" $CUSTOM "$chaddr" "$netaddr"
if [ ! -d $CUSTOM ]; then
$ERROR custom 3 "unable to retrieve configuration from $configdir"
exit 1
fi
# Compute the values of the SGI_ roboinst variables once,
# and store them in a file for use during the remainder
# of the miniroot session.
build_exports
test -s $MREXPORTS && . $MREXPORTS
# pre-process the mrconfig file to create a series
# of mrconfig.<phase> files that are access later in
# the miniroot session.
preprocess
# Verify that we understand this version of mrconfig
mrversion=`nawk '{ if ($1 != "") { print $1; exit } }' $MRCONFIG.version 2>&-`
if [ "$mrversion" = "" ]; then
mrversion=$DEFVERS
fi
$DEBUG mrversion $mrversion
if [ "$mrversion" -gt $MAXVERS ]; then
rm -rf $CUSTOM 2>&-
$ERROR custom 4 "mrconfig with invalid version $mrversion."
$ERROR custom 4 "This version of roboinst only understands versions up through $MAXVERS."
exit 1
fi
}
# Initialize, fetch contents of /custom directory.
startcustom()
{
# Log the fact that we've reached miniroot state.
$LOGOK live "retrieving configuration"
# get the configuration files
get_config
# is this a dry run?
if [ "$confirmation" = "no" ]; then
$INFO "Automatic installation canceled"
exit 1
fi
# Start remote logging if requested
loghost=`cat $MRCONFIG.loghost 2>&-`
if [ "$loghost" != "" ]; then
$INFO "loghost $loghost"
syslog_addhost $loghost
fi
# Log the fact that we've actually begun processing.
$LOGOK live "beginning processing"
# We are done with the initial processing.
# Run user init commands immediately.
runuser init
}
# live roboinst processing
runlive()
{
# Scripts catch but no-op SIGINT (from ^C) so that they
# are not disrupted by user hitting ^C, but still allow
# any subshells to default SIGINT. Ditto SIGQUIT (3), I guess.
trap : 2 3
LOGOK="logmsg ok"
ERROR="logmsg error"
WARNING="logmsg warning"
INFO="logmsg info"
#
# phase: start
#
startcustom
#
# phase: preinst
#
runuser preinst
#
# phase: inst
#
# Live roboinst cannot go interactive on error because it is
# probably running as an "at" job.
onerror=`nawk '{ if ($1 != "") { print $1; exit} }' $MRCONFIG.onerror 2>&-`
# inst will continue despite any errors
errflag="-Vabort_cmdfile_on_error:off"
if [ "$onerror" = wait ]; then
$WARNING "cannot wait on error in live mode, \"onerror wait\" ignored"
fi
if [ -s $MRCONFIG.inst ]; then
echo quit >> $MRCONFIG.inst
# execute inst, using the mrconfig.setenv.inst file
# that was determined during preprocessing
nocmd=0
if [ "$OSMAJ" -lt 6 ]; then
nocmd=1
elif [ "$OSMAJ" -eq 6 -a "$OSMIN" -lt 3 ]; then
nocmd=1
fi
if [ $nocmd = 1 ]; then
( test -s $MRCONFIG.setenv.inst && . $MRCONFIG.setenv.inst;
/usr/sbin/inst -M -Vdist:none -Vinteractive:off $errflag -Vsyslog:on $* < $MRCONFIG.inst )
else
( test -s $MRCONFIG.setenv.inst && . $MRCONFIG.setenv.inst;
/usr/sbin/inst -M -Vdist:none -c $MRCONFIG.inst -Vinteractive:off $errflag -Vsyslog:on $* )
fi
if [ $? = 0 ]; then
$LOGOK inst ok
else
$ERROR inst $? "Error occurred during software installation"
fi
fi
rm -f $TMPFILE 2>/dev/null
#
# phase: postinst
#
runuser postinst
#
# done with roboinst processing, clean up
#
$LOGOK done ok
syslog_restore
# clean up mrconfig directory
if [ "$debugmode" != "debug" ]; then
rm -fr $CUSTOM >/dev/null 2>&1
fi
exit 0
}
#------- functions for roboinst_start -------
# Send a log message to the tty, ignore all that syslog stuff
nologmsg()
{
if [ "$1" = "ok" ]; then
shift 2>/dev/null
shift 2>/dev/null
msg="$*"
elif [ "$1" = "error" ]; then
shift 2>/dev/null
shift 2>/dev/null
shift 2>/dev/null
msg="error: $*"
elif [ "$1" = "warning" ]; then
shift 2>/dev/null
msg="warning: $*"
elif [ "$1" = "info" ]; then
shift 2>/dev/null
msg="$*"
else
msg="$*"
fi
$ECHO "$msg"
}
# Make sure prom rev $1.$2 is compatible (for O2 systems only)
checkrev()
{
if [ "$1" = "" -o "$2" = "" ]; then
echo "WARNING: unable to determine PROM rev from hinv output"
echo "WARNING: roboinst requires PROM rev 4.4 or later on O2 systems"
elif [ "$1" -lt 4 -o "$1" -eq 4 -a $2 -lt 4 ]; then
$ERROR init 1 "roboinst requires PROM version 4.4 or later on O2 systems - install patch 2489 or successor"
return 1
fi
return 0
}
# Determine whether the sash version X.Y in the specified volume
# header ($1) is the same version (or more recent) than the version
# specified ($2.$3). Returns 0 if it is, or 1 if it is not.
# Sets SASHMAJ, SASHMIN and SASHMAINT variables as a side effect.
sashok()
{
SASHMAJ=
SASHMIN=
SASHMAINT=
eval `dvhtool -v g sash $TMPFILE $1 \
&& strings $TMPFILE \
| nawk '{ if (match($0, "^.*Version +([0-9]+\.)([0-9]+)(\.[0-9]*)?.*$")) {
sub("^.*Version +", "");
match($0, "^([0-9]+\.)([0-9]+)(\.[0-9]*)?");
split(substr($0, RSTART, RLENGTH), a, "\.");
printf "SASHMAJ=%s; SASHMIN=%s; SASHMAINT=%s;\n", a[1], a[2], a[3];
exit
}
}' 2>&- `
rm -f $TMPFILE
test "$SASHMAJ" -lt $2 -o \( "$SASHMAJ" -eq $2 -a "$SASHMIN" -lt $3 \) && return 1
return 0
}
# Copy the sash from the vh of the first disk ($1) to
# the vh of the second disk ($2).
copysash()
{
dvhtool -v get sash $TMPFILE $1 && dvhtool -v creat $TMPFILE sash $2
STATUS=$?
rm -f $TMPFILE
return $STATUS
}
#
# ---- end of functions ----
#
#-------------- begin main processing -----------------------
# check if we think we're already robo pogo
if [ -f $CHECKPOINT ]; then
$WARNING "Canceling previously scheduled installation"
if [ "$confirmation" != "no" ]; then
rm $CHECKPOINT
fi
fi
# don't do prom and netaddr checks if running live
if [ "$livemode" != "yes" ]; then
# roboinst requires prom rev 4.4 or later on O2
HSTATUS=0
hinv >$TMPFILE 2>&-
if grep 'IP32 Processor' $TMPFILE 1>&- 2>&- ; then
PMAJ=
PMIN=
eval `sed -n 's/.*FLASH.*PROM.*version[ \t]*\([0-9]*\)\.\([0-9]*\)[ \t]*/PMAJ=\1; PMIN=\2;/p' $TMPFILE`
checkrev "$PMAJ" "$PMIN"
HSTATUS=$?
fi
rm $TMPFILE 2>&-
test "$HSTATUS" = 0 || exit 1
# make sure nvram netaddr is sane, otherwise sash's bootp fails
NETADDR=`nvram netaddr 2>&-`
if [ "$NETADDR" = "192.0.2.1" ]; then
$ERROR init 1 "roboinst requires that the nvram netaddr variable be set to the"
$ERROR init 1 "appropriate value for this machine. Please set it using the"
$ERROR init 1 "nvram(1M) command."
fi
# need to map the nvram variable formats:
# *scsi(N)disk(M)rdisk(*)partition(P)
# dksc(N,M,P)
# to the filesystem formats:
# /dev/rdsk/dksNdMvh
# /dev/dsk/dksNdMsP
# NOTE: assumes that the existing values are valid, or will set garbage!
$DEBUG "syspart= $syspart"
case "$syspart" in
"")
# let dvhtool use the default
SYSPART=""
;;
yes|y)
# use what's in nvram
nvsyspart=`nvram SystemPartition`
SYSPART=`echo "$nvsyspart" | sed -n \
-e 's%^dksc(\([0-9]*\),\([0-9]*\),[0-9a-fA-F]*)%/dev/rdsk/dks\1d\2vh%p' \
-e 's%^.*scsi(\([0-9]*\))disk(\([0-9]*\))rdisk(.*)partition(.*)$%/dev/rdsk/dks\1d\2vh%p'`
$DEBUG "nvsyspart= $nvsyspart"
;;
[0-9]|[0-9][0-9])
# disk only change, edit the nvram vars
nvsyspart=`nvram SystemPartition`
if [ "$confirmation" != "no" ]; then
nvram SystemPartition `echo "$nvsyspart" | sed -n \
-e "s/^dksc(\([0-9]*\),.*$/dksc(\1,${syspart},8)/p" \
-e "s/disk([^)]*)/disk(${syspart})/p"`
$DEBUG "nvsyspart= $nvsyspart => `nvram SystemPartition`"
nvloadpart=`nvram OSLoadPartition`
nvram OSLoadPartition `echo "$nvloadpart" | sed -n \
-e "s/^dksc(\([0-9]*\),[0-9]*,\([0-9a-fA-F]*\))$/dksc(\1,${syspart},\2)/p" \
-e "s/disk([^)]*)/disk(${syspart})/p"`
$DEBUG "nvloadpart= $nvloadpart => `nvram OSLoadPartition`"
nvroot=`nvram root 2> /dev/null`
nvram root `echo $nvroot | sed -e 's/dks\([0-9]*\)d[0-9]*s\([0-9]*\)/dks\1d'${syspart}'s\2/'` 2>/dev/null
$DEBUG "nvroot= $nvroot => `nvram root`"
fi
sysbuss=`echo $nvsyspart | sed -n \
-e 's/^.*scsi(\([0-9]*\))disk.*$/\1/p' \
-e 's/^dksc(\([0-9]*\),[0-9]*,[0-9]*)$/\1/p`
SYSPART="/dev/rdsk/dks${sysbuss}d${syspart}vh"
;;
dksc\(*\))
# this is OSLoadPartition, assumed valid syntax for this system
SYSPART=`echo "$syspart" | sed \
-e 's%^dksc(\([0-9]*\),\([0-9]*\),.*)$%/dev/rdsk/dks\1d\2vh/%'`
if [ "$confirmation" != "no" ]; then
nvram SystemPartition `echo "$syspart" | sed -e 's/,[0-9a-fA-F]*)$/,8)/'`
nvram OSLoadPartition "$syspart"
nvram root `echo $syspart | sed \
-e 's/dksc(\([0-9]*\),\([0-9]*\),\([0-9]*\))/dks\1d\2s\3/'` 2>/dev/null
$DEBUG "root => `nvram root`"
fi
$DEBUG "syspart= $syspart"
;;
[a-z]*\))
# this is OSLoadPartition, assumed valid syntax for this system
SYSPART=`echo $syspart | sed \
-e 's%^.*scsi(\([0-9]*\))disk(\([0-9]*\))rdisk(.*)partition(.*)$%/dev/rdsk/dks\1d\2vh%'`
if [ "$confirmation" != "no" ]; then
nvram SystemPartition `echo "$syspart" | sed -e 's/([^(]*)$/(8)/'`
nvram OSLoadPartition "$syspart"
nvram root `echo $syspart | sed \
-e 's%^.*scsi(\([0-9]*\))disk(\([0-9]*\))rdisk(.*)partition(\([0-9]*\))$%dks\1d\2s\3%'` 2>/dev/null
$DEBUG "root => `nvram root`"
fi
$DEBUG "syspart= $syspart"
;;
*)
# badly formatted?
$ERROR init 1 "badly formatted OSLoadPartition value: \"${syspart}\""
SYSPART=""
exit 1
;;
esac
$DEBUG "SYSPART= $SYSPART"
# make sure sash is 6.5 or later, otherwise the miniroot boot will fail
badsash=""
if sashok "$SYSPART" 6 5 ; then
# 6.5 or later sash is in vh of disk we'll be booting
# the miniroot from
$DEBUG "booting with sash rev $SASHMAJ.$SASHMIN"
elif test "$SYSPART" != "" && \
test "`/sbin/stat -iq /dev/rvh`" != "`/sbin/stat -iq $SYSPART`" && \
sashok /dev/rvh 6 5 ; then
# This is an alternate disk install (-P) onto a disk other than
# the root drive, and there is a usable sash in the root volhdr.
# If it's not a dryrun, copy sash from root disk to alternate disk
if [ "$confirmation" != no ]; then
if copysash /dev/rvh "$SYSPART" && sashok "$SYSPART" 6 5 ; then
# Booting miniroot onto an alternate disk (not the root drive),
# and we successfully copied a recent sash from the root vh
# to the vh of the other disk.
$DEBUG "copied sash rev $SASHMAJ.$SASHMIN from root vh to $SYSPART"
else
# Copy failed
badsash=1
fi
else
$DEBUG "would copy sash rev $SASHMAJ.$SASHMIN from root vh to $SYSPART"
fi
else
# No usable sash found on root or alternate disk
badsash=1
fi
if [ "$badsash" = 1 ]; then
$ERROR init 1 "The correct version of sash does not appear to be installed"
$ERROR init 1 "in the volume header. Roboinst miniroot installations require"
$ERROR init 1 "an IRIX 6.5 or later version of sash. Install the roboinst"
$ERROR init 1 "client software on the target machine and see the discussion of"
$ERROR init 1 "the -P option in the roboinst(1M) manual page."
exit 1
fi
fi
OSMAJ=""
OSMIN=""
eval `uname -r | sed -n 's/^\([0-9]*\)\.\([0-9]*\).*/OSMAJ=\1; OSMIN=\2;/p' 2>&-`
OSVER="$OSMAJ.$OSMIN"
if [ "$bootdir" != "" ]; then
# get CPUBOARD to discover which sash to boot from
mkdir -p $TMPROOT/var/inst
touch $TMPROOT/var/inst/hist
ln -s $rbase/var/inst/roboinst $TMPROOT/var/inst/roboinst
echo admin hardware | /usr/sbin/inst -f none -r $TMPROOT -Vmenus:off 2>&1 > $TMPFILE
egrep '^CPUBOARD=|^MODE=' $TMPFILE > $TMPROOT/adminhw
cpu=`sed -n 's/^CPUBOARD=//p' $TMPROOT/adminhw | head -1`
mode=`sed -n 's/^MODE=//p' $TMPROOT/adminhw | head -1`
rm -rf $TMPROOT
# On 5.3 systems mode is implicitly 32bit
if [ "$cpu" != "" -a "$mode" = "" -a "$OSVER" = 5.3 ]; then
mode=32bit
fi
if [ "$cpu" = "" -o "$mode" = "" ]; then
while read tmpline; do
$ERROR init 1 "$tmpline"
done < $TMPFILE
$ERROR init 1 "Cannot determine hardware CPUBOARD and MODE, and as a"
$ERROR init 1 "result cannot determine whether to use the 32-bit sash"
$ERROR init 1 "or 64-bit sash to boot the miniroot environment - aborting."
$ERROR init 1 "Check to make sure that the inst program is functional."
rm -f $TMPFILE
abort 1
fi
rm -f $TMPFILE
if [ "$mode" = "32bit" -o "$cpu" = "IP19" ]; then
promtype="sashARCS";
else
promtype="sash64";
fi
$DEBUG "Using promtype $promtype"
fi
# get IP address of bootserver and configserver
confighost=`echo $configdir | nawk -F: '{print $1}'`
configpath=`echo $configdir | sed -e 's/^[^:]*://' -e 's|/$||'`
getipaddr $confighost
if [ "$IPADDR" = "0" ]; then
$ERROR init 1 "Unable to get IP address for configserver $confighost, aborting"
exit 1
fi
confighostip=$IPADDR
$DEBUG configserverIP $confighostip
# don't do bootfile and miniroot kernel checks if running live
if [ "$bootdir" != "" ]; then
# Determine if bootfile and miniroot kernel exist
boothost=`echo $bootdir | nawk -F: '{print $1}'`
bootpath=`echo $bootdir | sed -e 's/^[^:]*://' -e 's|/$||'`
bootsa=$bootpath/sa
bootunix=$bootpath/miniroot/unix.$cpu
if [ -x $BPCLT ]; then
bpsa=`$BPCLT -b $boothost:$bootsa | sed -n 's/^file=//p'`
bpunix=`$BPCLT -b $boothost:$bootunix | sed -n 's/^file=//p'`
else
$ERROR init 1 "$BPCLT not installed, aborting"
exit 1
fi
if [ "$bpsa" != "$bootsa" ]; then
$ERROR init 1 "Unable to read bootfile $boothost:$bootsa, aborting"
exit 1
fi
if [ "$bpunix" != "$bootunix" ]; then
$ERROR init 1 "Unable to read kernel $boothost:$bootunix, aborting"
exit 1
fi
fi
# get the configuration files
get_config
# check logging
loghost=`cat $MRCONFIG.loghost 2>&-`
$DEBUG "mrconfig loghost is $loghost"
if [ -f $MRCONFIG.disksetup ]; then
disksetup="disksetup"
$DEBUG "mrconfig disksetup"
fi
# clean up
rm -fr $CUSTOM >/dev/null 2>&1
if [ "$disksetup" = "disksetup" ]; then
disksetup="disksetup=true"
fi
# get IP address of loghost
if [ "$loghost" = "" ]; then
$ERROR init 1 "loghost not set in $configdir/mrconfig,"
$ERROR init 1 " logging will be local-only"
fi
getipaddr `hostname`
thisip=$IPADDR
loghostip=""
for host in $loghost ; do
if [ "$host" = "localhost" ]; then
IPADDR=$thisip
else
getipaddr $host
fi
if [ "$IPADDR" = "0" ]; then
$ERROR init 1 "Unable to get IP address for loghost $host, aborting"
exit 1
fi
loghostip="$loghostip $IPADDR"
done
$DEBUG "loghostip $loghostip"
# okay, everything looks good
if [ "$reportaddr" = "yes" ]; then
$ECHO "roboinst: PROMIFADDR -z $chaddr"
fi
# let's confirm
if [ "$confirmation" = "" ]; then
if [ "$livemode" != "yes" ]; then
ask "`gettxt ${msgfile}:1166 'Do you want to continue with the shutdown and proceed with\nautomatic miniroot installation? '`" 0
else
ask "`gettxt ${msgfile}:1167 'Do you want to continue with the automatic installation? '`" 0
fi
if [ $? -eq 0 ]; then
confirmation=no
else
confirmation=yes
fi
fi
# if not confirmed, this is a dryrun
if [ "$confirmation" = "no" ]; then
timestr=""
fi
# submit the job if a time was specified, otherwise take the machine DOWN:
# 1) create file in /var/inst to indicate robo has been requested
# 2) create file in volume header for roboinst
if [ "$timestr" != "" ]; then
liveopt=""
bootopt=""
if [ "$livemode" = "yes" ]; then
liveopt="-L"
fi
if [ "$bootdir" != "" ]; then
bootopt="-b $bootdir"
fi
# If an email address was specified, output goes there,
# otherwise quash all output so at doesn't send email.
if [ "$emailaddr" = "" ]; then
filter="1>&- 2>&-"
else
filter="2>&1 | /usr/sbin/Mail -s \"roboinst job completed\" $emailaddr"
fi
# + 1 minute is because 6.2/5.3 at now does not work
nocmd=0
if [ "$OSMAJ" -lt 6 ]; then
nocmd=1
elif [ "$OSMAJ" -eq 6 -a "$OSMIN" -lt 5 ]; then
nocmd=1
fi
if [ $nocmd = 1 -a "$timestr" = "now" ]; then
timestr="$timestr + 1 minute"
fi
atcmd="/bin/sh $0 -y $liveopt -c $confighostip:$configpath $bootopt $filter"
$DEBUG "scheduling $atcmd"
( echo "$atcmd" | /usr/bin/at $timestr 2>&1 &&
$ECHO "Automatic installation scheduled for $timestr" ) \
| grep -v executed
else
# if we're running live, don't set up volume header and reboot
if [ "$livemode" = "yes" ]; then
runlive
exit 0
fi
# need to rebuild bootfile in terms of IP address
TAPEDEV="bootp()$boothost:$bootsa"
BOOTFROM="$TAPEDEV($promtype)"
# need to parse out IP address for dlserver
cat <<EOF > $TMPFILE
0
BOOTARGS=mrmode=custom$debugmode $disksetup
BOOTFILE=$BOOTFROM
ENV:tapedevice=$TAPEDEV
ENV:dlserver=$boothost
ENV:mrconfig=$configdhcp$confighostip:$configpath
ENV:netaddr=$netaddr
ENV:netmask=$netmask
EOF
if [ "$confirmation" = "no" ]; then
if [ "$debugmode" = "debug" ]; then
$DEBUG "auto_mr:"
cat $TMPFILE
rm -f $TMPFILE > /dev/null 2>&1
fi
$ECHO "Automatic installation canceled"
exit 1
fi
cat <<EOF > $CHECKPOINT
#! /bin/sh
#Tag 0x00000f00
# $CHECKPOINT
# created by roboinst_start
# version $DEFVERS
LOGHOST="$loghostip"
cp /etc/syslog.conf /etc/syslog.conf.new.\$\$ 2>&-
for HOST in \$LOGHOST ; do
echo '*.debug;kern,syslog.none @'\$HOST >> /etc/syslog.conf.new.\$\$
done
cp /etc/syslog.conf /etc/syslog.conf.old.\$\$
mv /etc/syslog.conf.new.\$\$ /etc/syslog.conf
killall -HUP syslogd
logger -t roboinst "state=start status=1 error: failed to reach miniroot state"
mv /etc/syslog.conf.old.\$\$ /etc/syslog.conf
killall -HUP syslogd
EOF
chmod +x $CHECKPOINT
# now stuff the volume header and restart
/sbin/dvhtool -v creat $TMPFILE auto_mr $SYSPART 2>&1
if [ $? != 0 ]; then
rm -f $CHECKPOINT $TMPFILE > /dev/null 2>&1
$ECHO "Automatic installation did not start, dvhtool error"
exit 1
fi
rm -f $TMPFILE > /dev/null 2>&1
if [ "$loghost" != "" ]; then
syslog_addhost $loghost
logger -t roboinst "state=start status=0 restarting for automatic installation"
syslog_restore
fi
$ECHO "Automatic installation started"
if [ -x /etc/shutdown ] ; then
echo "3" | /etc/shutdown -y -i6 -g$grace
else
echo "3" | /sbin/init 6
fi
fi